/*
 * Created on Wed Jun 06 2018 by Ronnie Ren (zhaosong.ren) from Accenture
 *
 * Copyright (c) 2018 DingXing information & technology limited company.
 */

import { Injectable } from "@angular/core";
import { SqliteService } from "../../services/sqliteDB/sqlite.service";
import { Observable } from "rxjs/Observable";
import { JsonMappingUtil } from "../json-mapping-util";
import { ObjectDto } from "../../services/sqliteDB/object.dto";
import {ConditionFetch, ConditionPair} from "../../services/sqliteDB/condition-fetch";
import {WorkOrderDto} from "../dto/work-orders.dto";

@Injectable()
export class CurdService {

  constructor(private sqliteService: SqliteService) {

  }

  simpleFetch<T extends ObjectDto>(dto: { new(): T; }, filter = []) {
    return this.sqliteService.simpleFetch(dto, filter);
  }

  /*
  param: {
    filter: [],
    and: {

    },
    or: [{
        price: 32,
    }, {
        price: 1,
    }],
    like: {
        updateTime: "232"
    },
    page: {
      pageNo: 1,
      pageSize: 10
    }
  }
   */
  fetchByCondition<T extends ObjectDto>(dto: { new(): T; }, param = {}, orderBy: Array<string> = []) {
    // console.log(orderBy);
    return this.sqliteService.fetch(dto, param, orderBy);
  }

  observableFetchObjectsByPage<T extends ObjectDto>(
    dto: { new(): T; },
    andConditions: ConditionPair,
    orConditions: Array<ConditionPair> = [],
    pageSize: number = 1,
    pageNo: number = 1,
    orderBy = []): Observable<Array<any>> {

    let param = {
      and: andConditions,
      or: orConditions,
      page: {
        pageSize: pageSize,
        pageNo: pageNo,
      }
    };
    return Observable.fromPromise(this.sqliteService.fetch(dto, param, orderBy))
      .map((result: {results: Array<object>}) => {
        if (result && result.results) {
          let rows = Array.from(result.results);
          return rows.map((row) => {
            let objDto = new dto();
            JsonMappingUtil.MappingAllProp(row, objDto);
            return objDto;
          });
        }
        return [];
      });
  }

  observableFetchObjects<T extends ObjectDto>(
    dto: { new(): T; },
    andConditions: ConditionPair,
    orConditions: Array<ConditionPair> = [],
    orderBy = []): Observable<Array<any>> {
    let param = {
      and: andConditions,
      or: orConditions,
    };
    return Observable.fromPromise(this.sqliteService.fetch(dto, param, orderBy))
    .map((result: {results: Array<object>}) => {
      if (result && result.results) {
        let rows = Array.from(result.results);
        return rows.map((row) => {
          let objDto = new dto();
          JsonMappingUtil.MappingAllProp(row, objDto);
          return objDto;
        });
      }
      return [];
    });
  }

  addRow<T extends ObjectDto>(param: {
                            dto: { new(): T; }, mapObj
                            },
                              obj) {
    if (Array.isArray(obj)) {
      obj.forEach((item, index) => {
        return this.add(param, item);
      });
    } else {
      return this.add(param, obj);
    }
  }

  addRows<T extends ObjectDto>(dto: Array<T>) {
    return this.sqliteService.addRows(dto);
  }

  add<T extends ObjectDto>(param: {
                            dto: { new(): T; },
                            mapObj
                          },
                           obj: object) {
    let dtoObj = new param.dto();
    let mapData = new param.mapObj(obj);
    JsonMappingUtil.MappingAllProp(mapData, dtoObj);
    return this.sqliteService.add(dtoObj);
  }

  beginTransaction() {
    return this.sqliteService.beginTransaction();
  }

  updateRows<T extends ObjectDto>(dtos: Array<T>, filterKeys: Array<string>) {
    return this.sqliteService.updateRows(dtos, filterKeys);
  }

  updateRow<T extends ObjectDto>(dto: T, filterKeyValue: ConditionPair): Observable<boolean> {
    return this.sqliteService.updateRow(dto, filterKeyValue);
  }

  update<T extends ObjectDto>(param: {
                              dto: { new(): T; }, mapObj
                              },
                              obj,
                              filter: ConditionFetch) {
    let dtoObj = new param.dto();
    JsonMappingUtil.MappingAllProp(new param.mapObj(obj), dtoObj);
    return this.sqliteService.update({
      dto: param.dto,
      dtoObject: dtoObj,
      filter: filter
    });
  }

  remove<T extends ObjectDto>(dto: { new(): T; }, filter: ConditionFetch) {
    return this.sqliteService.remove(dto, filter
    //   {
    //   and: {
    //     areaId: "510000",
    //   },
    //   // or: [{
    //   //     price: 3,
    //   // }]
    // }
    );
  }

  addColumn<T extends ObjectDto>(dto: { new(): T; }) {
    this.sqliteService.addColumn(dto, {
      imgss: "text"
    });
  }

  dropTable<T extends ObjectDto>(dto: { new(): T; }) {
    this.sqliteService.dropTable(dto);
  }

  createTable<T extends ObjectDto>(dto: { new(): T; }) {
    return this.sqliteService.creatTable(dto);
  }

}
